package com.common.utils;

import com.google.gson.Gson;
import com.system.domain.T_operation_log;
import com.system.mapper.T_operation_logMapper;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

//import com.alibaba.fastjson.JSON;

/**
 * @author davexin
 */

@Component
public class VisitInterceptor implements HandlerInterceptor {

	private static final Logger log = Logger.getLogger(VisitInterceptor.class);
	@Resource
	private T_operation_logMapper mapper;
	private long startTime = System.currentTimeMillis();

	/*
	 * 访问请求日志记录
	 * (non-Javadoc)
	 * @see org.springframework.web.servlet.HandlerInterceptor#preHandle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object)
	 */
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		//请求的路径
		String path = request.getContextPath();
		String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
		String  url  =  "http://"  +  request.getServerName()  +  ":"  +  request.getServerPort()  +  request.getContextPath()+request.getServletPath(); //.substring(0,request.getServletPath().lastIndexOf("/")+1);
		Gson  gson = new Gson();
		T_operation_log operlog = new T_operation_log();
		String starttime = DateUtil.getCurrDateTime();
		String username = (String) request.getSession().getAttribute("FREE_CURRENT_USER");
		StringBuffer sb = new StringBuffer();
		
		try {
			//如果是HandlerMethod类型，可获取对应类名、方法名等信息；
			if (handler instanceof HandlerMethod) {
				HandlerMethod handlerMethod = (HandlerMethod) handler;
				String beanName = handlerMethod.getBean().getClass().toString();//类
				String methodName = handlerMethod.getMethod().getName();//方法名称
				//if(methodName.equals("error") || methodName.equals("success")) {
				//	return false;
				//}
				
				String uri = request.getRequestURI();//请求路径
				String remoteAddr = getIpAddr(request);//请求ip
				String method = request.getMethod(); //请求方式
				Map<String,String[]> pramMap = request.getParameterMap();
	
				//加工成json格式字符串；
				int count = 0;
				sb.append("{");
				sb.append("\"username\":\"" + username+ "\",\"startTime\":\"" + starttime+ "\",\"className\":\"" + beanName+"\",\"methodName\":\"" + methodName+"\",\"uri\":\"" + uri+"\",\"remoteAddr\":\"" + remoteAddr+"\",\"requestMethod\":\"" + method+"\"");
				
				for(Map.Entry<String, String[]> entry:pramMap.entrySet()){  
					sb.append( ",\""  + entry.getKey() + "\":\"" + request.getParameter(entry.getKey()) + "\"");
					count ++;
				} 
				sb.append("}");
				
				//执行保存操作记录到数据库
				if (null == username||"".equals(username)) {
					log.error("------preHandle 业务操作日志&&&&&&方法执行前Start：-》用户未登录或者直接跳转（请求方法中没传递httprequest），获取不到用户session操作信息------");
					username = "用户未登录或者直接跳转";
				} else {
					log.error("------preHandle 业务操作日志&&&&&&方法执行前Start：-》获取到当前操作用户为:" + username+"------");
				}
				log.error("------preHandle 业务操作日志&&&&&&方法执行前：-》获取到当前用户操作业务类名字:" + beanName + ";操作方法名字:" + methodName+"------");
				log.error("------preHandle 业务操作日志&&&&&&方法执行前End：获取到当前用户操作业务参数值-》:" + sb.toString() +"------");
				
				//记录跟踪审计信息				
				operlog.setUserid(username);
				operlog.setOperation_start_tm(starttime);
				operlog.setUrl("访问类名："+ beanName +",方法名:"+ methodName );
				operlog.setArgs(sb.toString());
				operlog.setSession_id(Thread.currentThread().getId()+"");
				operlog.setSystemid(""); //待记录为子系统id或者从系统常亮中读取；

				if(null!=starttime|| !"".equals(starttime)){
					mapper.save(operlog);
				}
			}

		}catch(Exception e) {
			e.printStackTrace();
		}

		return true;
	}

	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2,
						   ModelAndView arg3) throws Exception {
		log.info("------postHandle 业务操作日志 HandlerInterceptor  请求处理时间为:"+(System.currentTimeMillis() - startTime)/1000 +" （毫秒）");
	}

	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2,
								Exception arg3) throws Exception {
		log.info("------afterCompletion 业务操作日志 请求处理时间为:"+(System.currentTimeMillis() - startTime)/1000 +" （毫秒）");
	}

	/**
	 *  根据传入的访问对象获取对象具体方法属性及属性值组装map中；
	 *  此时只能处理post过来的是一个对象，如果页面上有非对象属性，则需要在上面方法中再获取其它属性值；
	 * @param obj
	 * @return
	 */
	public Map<String, Object> getKeyAndValue(Object obj) {
		Map<String, Object> map = new HashMap<>();
		// 得到类对象
		Class userCla = (Class) obj.getClass();
		/* 得到类中的所有属性集合 */
		Field[] fs = userCla.getDeclaredFields();
		for (int i = 0; i < fs.length; i++) {
			Field f = fs[i];
			f.setAccessible(true); // 设置些属性是可以访问的
			Object val = new Object();
			try {
				val = f.get(obj);
				// 得到此属性的值
				map.put(f.getName(), val);// 设置键值
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		return map;
	}

	/**
	 * 请求参数拼装
	 * 
	 * @param paramsArray
	 * @return
	 */
	/*   private String argsArrayToString(Object[] paramsArray) {
        String params = "";
        if (paramsArray != null && paramsArray.length > 0) {
            for (int i = 0; i < paramsArray.length; i++) {
                Object jsonObj = JSON.toJSON(paramsArray[i]);
                params += jsonObj.toString() + " ";
            }
        }
        return params.trim();
    }*/

	//获取客户端IP
	private String getIpAddr(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		return ip;
	}

}